From fce50c833496d8c07a1d189807d81be15875431c Mon Sep 17 00:00:00 2001 From: Florian Fischer Date: Tue, 24 Jul 2018 11:09:34 +0200 Subject: move c benchmarks in benchmarks subdir --- Makefile | 21 ++++-- bench.py | 3 +- bench_conprod.c | 165 --------------------------------------------- bench_loop.c | 114 ------------------------------- benchmarks/bench_conprod.c | 165 +++++++++++++++++++++++++++++++++++++++++++++ benchmarks/bench_loop.c | 114 +++++++++++++++++++++++++++++++ common_targets.py | 4 +- 7 files changed, 299 insertions(+), 287 deletions(-) delete mode 100644 bench_conprod.c delete mode 100644 bench_loop.c create mode 100644 benchmarks/bench_conprod.c create mode 100644 benchmarks/bench_loop.c diff --git a/Makefile b/Makefile index c515149..c7da232 100644 --- a/Makefile +++ b/Makefile @@ -2,8 +2,9 @@ .DEFAULT_GOAL = all -C_SOURCES = $(shell find . -name "*.c") -CC_SOURCES = $(shell find . -name "*.cc") +SRCDIR=benchmarks +C_SOURCES = $(shell find $(SRCDIR) -name "*.c") +CC_SOURCES = $(shell find $(SRCDIR) -name "*.cc") VERBOSE = OBJDIR = ./build @@ -26,11 +27,19 @@ OBJECTS = $(notdir $(CC_SOURCES:.cc=.o)) $(notdir $(C_SOURCES:.c=.o)) OBJPRE = $(addprefix $(OBJDIR)/,$(OBJECTS)) MAKEFILE_LIST = Makefile -all: $(OBJDIR)/bench_loop $(OBJDIR)/bench_conprod +TARGETS = $(OBJPRE:.o=) -bench: all - @if test \( ! \( -d bench.d \) \) ;then mkdir -p bench.d;fi - bash -c "./bench.py" +all: $(TARGETS) + +$(OBJDIR)/cache-thrash: $(OBJDIR)/cache-thrash.o + @echo "ld $@" + @if test \( ! \( -d $(@D) \) \) ;then mkdir -p $(@D);fi + $(VERBOSE) $(CXX) -pthread -o $@ $^ + +$(OBJDIR)/cache-scratch: $(OBJDIR)/cache-scratch.o + @echo "ld $@" + @if test \( ! \( -d $(@D) \) \) ;then mkdir -p $(@D);fi + $(VERBOSE) $(CXX) -pthread -o $@ $^ $(OBJDIR)/bench_conprod: $(OBJDIR)/bench_conprod.o @echo "ld $@" diff --git a/bench.py b/bench.py index c7d70f7..4ee0232 100755 --- a/bench.py +++ b/bench.py @@ -2,6 +2,7 @@ import argparse +from falsesharing import falsesharing from loop import loop # from bench_conprod import conprod from mysql import mysql @@ -14,7 +15,7 @@ parser.add_argument("-v", "--verbose", help="more output", action='store_true') parser.add_argument("-b", "--benchmarks", help="benchmarks to run", nargs='+') -benchmarks = [loop, mysql] +benchmarks = [loop, mysql, falsesharing] def main(): args = parser.parse_args() diff --git a/bench_conprod.c b/bench_conprod.c deleted file mode 100644 index 3b349ce..0000000 --- a/bench_conprod.c +++ /dev/null @@ -1,165 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -static size_t _rand() { - static __thread size_t seed = 123456789; - size_t a = 1103515245; - size_t c = 12345; - size_t m = 1 << 31; - seed = (a * seed + c) % m; - return seed; -} - -typedef struct Store { - pthread_mutex_t mutex; - sem_t free; - sem_t avail; - int toconsum; - int pos; - void* ptrs[100]; -} Store; - -typedef struct ThreadArgs { - bool isconsumer; - Store* store; - int allocations; - int maxsize; -} ThreadArgs; - -static void* malloc_then_write(size_t size) { - void* ptr = malloc(size); - // Write to ptr - *((char*)ptr) = '!'; - return ptr; -} - -static void read_then_free(void* ptr) { - // Read before free - char s __attribute__((unused)) = *((char*)ptr); - free(ptr); -} -static void* test_thread_func(void* arg) { - ThreadArgs* args = (ThreadArgs*)arg; - Store* store = args->store; - - if (args->isconsumer) - { - while (__sync_sub_and_fetch(&store->toconsum, 1) > -1) - { - sem_wait(&store->avail); - pthread_mutex_lock(&store->mutex); - void* ptr = store->ptrs[store->pos]; - store->pos--; - pthread_mutex_unlock(&store->mutex); - sem_post(&store->free); - read_then_free(ptr); - } - } else { - for (int i = 0; i < args->allocations; i++) - { - void* ptr = malloc_then_write((_rand() % args->maxsize) + 1); - sem_wait(&store->free); - pthread_mutex_lock(&store->mutex); - store->pos++; - store->ptrs[store->pos] = ptr; - pthread_mutex_unlock(&store->mutex); - sem_post(&store->avail); - } - } - - return NULL; -} - -int main(int argc, char* argv[]) { - pthread_t* threads; - int nstores; - Store* stores; - int consumers; - int producers; - int num_threads; - int allocations; - int maxsize; - struct ThreadArgs* thread_args; - - if (argc < 6) { - fprintf(stderr, "Usage: %s \n", argv[0]); - return 1; - } - - nstores = atoi(argv[1]); - consumers = atoi(argv[2]); - if (nstores > consumers) - { - fprintf(stderr, "Only %d consumers but %d stores!\n", consumers, nstores); - } - - producers = atoi(argv[3]); - if (nstores > producers) - { - fprintf(stderr, "Only %d producers but %d stores!\n", producers, nstores); - } - - num_threads = consumers + producers; - allocations = atoi(argv[4]); - maxsize = atoi(argv[5]); - - threads = (pthread_t*)malloc(num_threads * sizeof(pthread_t)); - thread_args = (ThreadArgs*)malloc(num_threads * sizeof(ThreadArgs)); - stores = (Store*)malloc(nstores * sizeof(Store)); - if (threads == 0 || thread_args == 0 || stores == 0) - { - perror("malloc"); - return 1; - } - - // Init stores - for (int i = 0; i < nstores; i++) - { - stores[i].pos = -1; - if (0 != pthread_mutex_init(&stores[i].mutex, 0)) { perror("mutex_init"); return 1; } - if (0 != sem_init(&stores[i].free, 0, 100)) { perror("sem_init"); return 1; } - if (0 != sem_init(&stores[i].avail, 0, 0)) { perror("sem_init"); return 1; } - } - - // Build up thread_args - for (int i = 0; i < num_threads; i++) - { - thread_args[i].store = &stores[i % nstores]; - thread_args[i].maxsize = maxsize; - thread_args[i].allocations = allocations; - - if ( i < producers) { - thread_args[i].isconsumer = false; - stores[i % nstores].toconsum += allocations; - } else - thread_args[i].isconsumer = true; - } - - for (int i = 0; i < num_threads; i++) { - if (0 != pthread_create(&threads[i], NULL, test_thread_func, &thread_args[i])) { - perror("pthread_create"); - return 1; - } - } - - for (int i = 0; i < num_threads; i++) { - if (0 != pthread_join(threads[i], NULL)) { - perror("pthread_join"); - return 1; - } - } - - FILE* f = stdout; - if (argc == 7) - f = fopen(argv[6], "w"); - malloc_info(0, f); - if (argc == 7) - fclose(f); - - return 0; -} diff --git a/bench_loop.c b/bench_loop.c deleted file mode 100644 index b1c8d13..0000000 --- a/bench_loop.c +++ /dev/null @@ -1,114 +0,0 @@ -#include -#include -#include -#include -#include - - -static size_t _rand() { - static __thread size_t seed = 123456789; - size_t a = 1103515245; - size_t c = 12345; - size_t m = 1 << 31; - seed = (a * seed + c) % m; - return seed; -} - -/* -* Available Benchmarks: -* 1.x: do malloc()/free() in a loop -* 1: simple loop -* 1.1: keep num_kept_allocations befor freeing -* 1.2: keep num_kept_allocations then free all stored -*/ - -typedef struct ThreadArgs { - double benchmark; - int allocations; - int num_kept_allocations; - int max_size; -} ThreadArgs; - -static void* malloc_then_write(size_t size) { - void* ptr = malloc(size); - // Write to ptr - *((char*)ptr) = '!'; - return ptr; -} - -static void read_then_free(void* ptr) { - // Read before free - char s __attribute__((unused)) = *((char*)ptr); - free(ptr); -} -static void* test_thread_func(void* arg) { - ThreadArgs* args = (ThreadArgs*)arg; - void** ptrs = (void**)calloc(args->num_kept_allocations, sizeof(void*)); - - for(int i = 0; i < args->allocations; i++) { - int pos = i % args->num_kept_allocations; - - if (args->benchmark == 1.1) { - if (i >= args->num_kept_allocations) { - read_then_free(ptrs[pos]); - } - } - - if (args->benchmark == 1.2) { - if (pos == 0 && ptrs[pos] != NULL) { - for (int y = 0; y < args->num_kept_allocations; y++) { - read_then_free(ptrs[y]); - } - } - } - - ptrs[pos] = malloc_then_write((_rand() % args->max_size) + 1); - - if (args->benchmark == 1.0) { - read_then_free(ptrs[pos]); - } - } - return NULL; -} - -int main(int argc, char* argv[]) { - pthread_t* threads; - int num_threads; - struct ThreadArgs thread_args; - - if (argc < 6) { - fprintf(stderr, "Usage: %s \n", argv[0]); - return 1; - } - - thread_args.benchmark = atof(argv[1]); - num_threads = atoi(argv[2]); - thread_args.allocations = atoi(argv[3]); - thread_args.max_size = atoi(argv[4]); - thread_args.num_kept_allocations = atoi(argv[5]); - - threads = (pthread_t*)malloc(num_threads * sizeof(pthread_t)); - - for (int i = 0; i < num_threads; i++) { - if (0 != pthread_create(&threads[i], NULL, test_thread_func, &thread_args)) { - perror("pthread_create"); - return 1; - } - } - - for(int i = 0; i < num_threads; i++) { - if (0 != pthread_join(threads[i], NULL)) { - perror("pthread_join"); - return 1; - } - } - - FILE* f = stdout; - if (argc == 7) - f = fopen(argv[6], "w"); - malloc_info(0, f); - if (argc == 7) - fclose(f); - - return 0; -} diff --git a/benchmarks/bench_conprod.c b/benchmarks/bench_conprod.c new file mode 100644 index 0000000..3b349ce --- /dev/null +++ b/benchmarks/bench_conprod.c @@ -0,0 +1,165 @@ +#include +#include +#include +#include +#include +#include +#include + +static size_t _rand() { + static __thread size_t seed = 123456789; + size_t a = 1103515245; + size_t c = 12345; + size_t m = 1 << 31; + seed = (a * seed + c) % m; + return seed; +} + +typedef struct Store { + pthread_mutex_t mutex; + sem_t free; + sem_t avail; + int toconsum; + int pos; + void* ptrs[100]; +} Store; + +typedef struct ThreadArgs { + bool isconsumer; + Store* store; + int allocations; + int maxsize; +} ThreadArgs; + +static void* malloc_then_write(size_t size) { + void* ptr = malloc(size); + // Write to ptr + *((char*)ptr) = '!'; + return ptr; +} + +static void read_then_free(void* ptr) { + // Read before free + char s __attribute__((unused)) = *((char*)ptr); + free(ptr); +} +static void* test_thread_func(void* arg) { + ThreadArgs* args = (ThreadArgs*)arg; + Store* store = args->store; + + if (args->isconsumer) + { + while (__sync_sub_and_fetch(&store->toconsum, 1) > -1) + { + sem_wait(&store->avail); + pthread_mutex_lock(&store->mutex); + void* ptr = store->ptrs[store->pos]; + store->pos--; + pthread_mutex_unlock(&store->mutex); + sem_post(&store->free); + read_then_free(ptr); + } + } else { + for (int i = 0; i < args->allocations; i++) + { + void* ptr = malloc_then_write((_rand() % args->maxsize) + 1); + sem_wait(&store->free); + pthread_mutex_lock(&store->mutex); + store->pos++; + store->ptrs[store->pos] = ptr; + pthread_mutex_unlock(&store->mutex); + sem_post(&store->avail); + } + } + + return NULL; +} + +int main(int argc, char* argv[]) { + pthread_t* threads; + int nstores; + Store* stores; + int consumers; + int producers; + int num_threads; + int allocations; + int maxsize; + struct ThreadArgs* thread_args; + + if (argc < 6) { + fprintf(stderr, "Usage: %s \n", argv[0]); + return 1; + } + + nstores = atoi(argv[1]); + consumers = atoi(argv[2]); + if (nstores > consumers) + { + fprintf(stderr, "Only %d consumers but %d stores!\n", consumers, nstores); + } + + producers = atoi(argv[3]); + if (nstores > producers) + { + fprintf(stderr, "Only %d producers but %d stores!\n", producers, nstores); + } + + num_threads = consumers + producers; + allocations = atoi(argv[4]); + maxsize = atoi(argv[5]); + + threads = (pthread_t*)malloc(num_threads * sizeof(pthread_t)); + thread_args = (ThreadArgs*)malloc(num_threads * sizeof(ThreadArgs)); + stores = (Store*)malloc(nstores * sizeof(Store)); + if (threads == 0 || thread_args == 0 || stores == 0) + { + perror("malloc"); + return 1; + } + + // Init stores + for (int i = 0; i < nstores; i++) + { + stores[i].pos = -1; + if (0 != pthread_mutex_init(&stores[i].mutex, 0)) { perror("mutex_init"); return 1; } + if (0 != sem_init(&stores[i].free, 0, 100)) { perror("sem_init"); return 1; } + if (0 != sem_init(&stores[i].avail, 0, 0)) { perror("sem_init"); return 1; } + } + + // Build up thread_args + for (int i = 0; i < num_threads; i++) + { + thread_args[i].store = &stores[i % nstores]; + thread_args[i].maxsize = maxsize; + thread_args[i].allocations = allocations; + + if ( i < producers) { + thread_args[i].isconsumer = false; + stores[i % nstores].toconsum += allocations; + } else + thread_args[i].isconsumer = true; + } + + for (int i = 0; i < num_threads; i++) { + if (0 != pthread_create(&threads[i], NULL, test_thread_func, &thread_args[i])) { + perror("pthread_create"); + return 1; + } + } + + for (int i = 0; i < num_threads; i++) { + if (0 != pthread_join(threads[i], NULL)) { + perror("pthread_join"); + return 1; + } + } + + FILE* f = stdout; + if (argc == 7) + f = fopen(argv[6], "w"); + malloc_info(0, f); + if (argc == 7) + fclose(f); + + return 0; +} diff --git a/benchmarks/bench_loop.c b/benchmarks/bench_loop.c new file mode 100644 index 0000000..b1c8d13 --- /dev/null +++ b/benchmarks/bench_loop.c @@ -0,0 +1,114 @@ +#include +#include +#include +#include +#include + + +static size_t _rand() { + static __thread size_t seed = 123456789; + size_t a = 1103515245; + size_t c = 12345; + size_t m = 1 << 31; + seed = (a * seed + c) % m; + return seed; +} + +/* +* Available Benchmarks: +* 1.x: do malloc()/free() in a loop +* 1: simple loop +* 1.1: keep num_kept_allocations befor freeing +* 1.2: keep num_kept_allocations then free all stored +*/ + +typedef struct ThreadArgs { + double benchmark; + int allocations; + int num_kept_allocations; + int max_size; +} ThreadArgs; + +static void* malloc_then_write(size_t size) { + void* ptr = malloc(size); + // Write to ptr + *((char*)ptr) = '!'; + return ptr; +} + +static void read_then_free(void* ptr) { + // Read before free + char s __attribute__((unused)) = *((char*)ptr); + free(ptr); +} +static void* test_thread_func(void* arg) { + ThreadArgs* args = (ThreadArgs*)arg; + void** ptrs = (void**)calloc(args->num_kept_allocations, sizeof(void*)); + + for(int i = 0; i < args->allocations; i++) { + int pos = i % args->num_kept_allocations; + + if (args->benchmark == 1.1) { + if (i >= args->num_kept_allocations) { + read_then_free(ptrs[pos]); + } + } + + if (args->benchmark == 1.2) { + if (pos == 0 && ptrs[pos] != NULL) { + for (int y = 0; y < args->num_kept_allocations; y++) { + read_then_free(ptrs[y]); + } + } + } + + ptrs[pos] = malloc_then_write((_rand() % args->max_size) + 1); + + if (args->benchmark == 1.0) { + read_then_free(ptrs[pos]); + } + } + return NULL; +} + +int main(int argc, char* argv[]) { + pthread_t* threads; + int num_threads; + struct ThreadArgs thread_args; + + if (argc < 6) { + fprintf(stderr, "Usage: %s \n", argv[0]); + return 1; + } + + thread_args.benchmark = atof(argv[1]); + num_threads = atoi(argv[2]); + thread_args.allocations = atoi(argv[3]); + thread_args.max_size = atoi(argv[4]); + thread_args.num_kept_allocations = atoi(argv[5]); + + threads = (pthread_t*)malloc(num_threads * sizeof(pthread_t)); + + for (int i = 0; i < num_threads; i++) { + if (0 != pthread_create(&threads[i], NULL, test_thread_func, &thread_args)) { + perror("pthread_create"); + return 1; + } + } + + for(int i = 0; i < num_threads; i++) { + if (0 != pthread_join(threads[i], NULL)) { + perror("pthread_join"); + return 1; + } + } + + FILE* f = stdout; + if (argc == 7) + f = fopen(argv[6], "w"); + malloc_info(0, f); + if (argc == 7) + fclose(f); + + return 0; +} diff --git a/common_targets.py b/common_targets.py index 177168b..1fd6af3 100644 --- a/common_targets.py +++ b/common_targets.py @@ -1,3 +1,5 @@ common_targets = {"klmalloc" : ("", "targets/libklmalloc.so"), "libc" : ("", ""), # libc - "tcmalloc" : ("", "targets/libtcmalloc.so")} + "tcmalloc" : ("", "targets/libtcmalloc.so"), + "jemalloc" : ("", "targets/libjemalloc.so"), + "hoard" : ("", "targets/libhoard.so")} -- cgit v1.2.3