diff options
| -rw-r--r-- | src/Makefile | 6 | ||||
| -rw-r--r-- | src/align_to_cl.c | 240 | ||||
| -rw-r--r-- | src/allocators/tcmalloc.py | 25 | ||||
| -rw-r--r-- | src/allocators/tcmalloc/tcmalloc_2.7_cacheline_exclusive.patch | 26 | ||||
| -rw-r--r-- | src/allocators/tcmallocs.py | 26 |
5 files changed, 315 insertions, 8 deletions
diff --git a/src/Makefile b/src/Makefile index 71b4967..53f8f97 100644 --- a/src/Makefile +++ b/src/Makefile @@ -14,7 +14,7 @@ MEMSIZE_KB=$(shell free -t | tail -1 | tr -s ' ' | cut -d ' ' -f 2) MEMSIZE="$(MEMSIZE_KB) * 1024l" TOOLS = print_status_on_exit.so exec sig_handlers.so -ALLOCS = chattymalloc.so bumpptr_alloc.so speedymalloc.so +ALLOCS = chattymalloc.so bumpptr_alloc.so speedymalloc.so align_to_cl.so TARGETS = $(addprefix $(OBJDIR)/allocators/,$(ALLOCS)) $(addprefix $(OBJDIR)/,$(TOOLS)) .PHONY: all clean @@ -29,6 +29,10 @@ $(OBJDIR)/allocators/speedymalloc.so: speedymalloc.c Makefile @if test \( ! \( -d $(@D) \) \) ;then mkdir -p $(@D);fi $(CC) $(LDFLAGS) -shared -DMEMSIZE=$(MEMSIZE) $(CFLAGS) -o $@ $< +$(OBJDIR)/allocators/align_to_cl.so: align_to_cl.c Makefile + @if test \( ! \( -d $(@D) \) \) ;then mkdir -p $(@D);fi + $(CC) $(LDFLAGS) -shared $(CFLAGS) -o $@ $< -ldl + $(OBJDIR)/allocators/chattymalloc.so: chattymalloc.h chattymalloc.c Makefile @if test \( ! \( -d $(@D) \) \) ;then mkdir -p $(@D);fi $(CC) $(LDFLAGS) -shared $(CFLAGS) -o $@ chattymalloc.c -ldl diff --git a/src/align_to_cl.c b/src/align_to_cl.c new file mode 100644 index 0000000..e54f065 --- /dev/null +++ b/src/align_to_cl.c @@ -0,0 +1,240 @@ +/* +Copyright 2018-2020 Florian Fischer <florian.fl.fischer@fau.de> + +This file is part of allocbench. + +allocbench is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +allocbench is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with allocbench. If not, see <http://www.gnu.org/licenses/>. +*/ + +#define _GNU_SOURCE +#include <dlfcn.h> +#include <errno.h> +#include <fcntl.h> +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#define CACHE_LINE 64 + +static char tmpbuff[4096]; +static unsigned long tmppos = 0; +static unsigned long tmpallocs = 0; + +/*========================================================= + * intercepted functions + */ + +static void* (*next_malloc)(size_t size); +static void (*next_free)(void* ptr); +static void* (*next_calloc)(size_t nmemb, size_t size); +static void* (*next_realloc)(void* ptr, size_t size); +static void* (*next_memalign)(size_t alignment, size_t size); +static int (*next_posix_memalign)(void** memptr, size_t alignment, size_t size); +static void* (*next_valloc)(size_t size); +static void* (*next_pvalloc)(size_t size); +static void* (*next_aligned_alloc)(size_t alignment, size_t size); +static int (*next_malloc_stats)(); + +static void __attribute__((constructor)) +init() +{ + next_malloc = dlsym(RTLD_NEXT, "malloc"); + next_free = dlsym(RTLD_NEXT, "free"); + next_calloc = dlsym(RTLD_NEXT, "calloc"); + next_realloc = dlsym(RTLD_NEXT, "realloc"); + next_memalign = dlsym(RTLD_NEXT, "memalign"); + next_posix_memalign = dlsym(RTLD_NEXT, "posix_memalign"); + next_valloc = dlsym(RTLD_NEXT, "valloc"); + next_pvalloc = dlsym(RTLD_NEXT, "pvalloc"); + next_aligned_alloc = dlsym(RTLD_NEXT, "aligned_alloc"); + next_malloc_stats = dlsym(RTLD_NEXT, "malloc_stats"); + + if (!next_malloc || !next_free || !next_calloc || !next_realloc || + !next_memalign) { + fprintf(stderr, "Can't load core functions with `dlsym`: %s\n", dlerror()); + exit(1); + } + if (!next_posix_memalign) + fprintf(stderr, "Can't load posix_memalign with `dlsym`: %s\n", dlerror()); + if (!next_valloc) + fprintf(stderr, "Can't load valloc with `dlsym`: %s\n", dlerror()); + if (!next_pvalloc) + fprintf(stderr, "Can't load pvalloc with `dlsym`: %s\n", dlerror()); + if (!next_aligned_alloc) + fprintf(stderr, "Can't load aligned_alloc with `dlsym`: %s\n", dlerror()); + if (!next_malloc_stats) + fprintf(stderr, "Can't load malloc_stats with `dlsym`: %s\n", dlerror()); +} + +static void align_up_size(size_t* size) +{ + size_t s = *size; + size_t a = (s + CACHE_LINE + 1) & ~(CACHE_LINE - 1); + *size = a; +} + +void* +malloc(size_t size) +{ + static int initializing = 0; + + if (next_malloc == NULL) { + if (!initializing) { + initializing = 1; + init(); + initializing = 0; + + } else { + void* retptr = tmpbuff + tmppos; + tmppos += size; + ++tmpallocs; + + if (tmppos < sizeof(tmpbuff)) { + return retptr; + } else { + fprintf(stderr, "%d in %d allocs\n", tmppos, tmpallocs); + fprintf(stderr, + "jcheck: too much memory requested during initialisation - " + "increase tmpbuff size\n"); + exit(1); + } + } + } + + align_up_size(&size); + void* ptr = next_malloc(size); + return ptr; +} + +void +free(void* ptr) +{ + // something wrong if we call free before one of the allocators! + if (next_malloc == NULL) + init(); + if (!(ptr >= (void*)tmpbuff && ptr <= (void*)(tmpbuff + tmppos))) { + next_free(ptr); + } +} + +void* +realloc(void* ptr, size_t size) +{ + if (next_realloc == NULL) { + void* nptr = malloc(size); + if (nptr && ptr) { + memmove(nptr, ptr, size); + free(ptr); + } + return nptr; + } + + align_up_size(&size); + void* nptr = next_realloc(ptr, size); + return nptr; +} + +void* +calloc(size_t nmemb, size_t size) +{ + if (next_calloc == NULL) { + void* ptr = malloc(nmemb * size); + if (ptr) + memset(ptr, 0, nmemb * size); + return ptr; + } + + align_up_size(&size); + void* ptr = next_calloc(nmemb, size); + return ptr; +} + +void* +memalign(size_t alignment, size_t size) +{ + if (next_memalign == NULL) { + fprintf(stderr, "called memalign before or during init\n"); + exit(1); + } + + align_up_size(&size); + void* ptr = next_memalign(alignment, size); + return ptr; +} + +int +posix_memalign(void** memptr, size_t alignment, size_t size) +{ + if (next_posix_memalign == NULL) { + fprintf(stderr, "called posix_memalign before or during init\n"); + exit(1); + } + + align_up_size(&size); + int ret = next_posix_memalign(memptr, alignment, size); + return ret; +} + +void* +valloc(size_t size) +{ + if (next_valloc == NULL) { + fprintf(stderr, "called valloc before or during init"); + exit(1); + } + + align_up_size(&size); + void* ptr = next_valloc(size); + return ptr; +} + +void* +pvalloc(size_t size) +{ + if (next_pvalloc == NULL) { + fprintf(stderr, "called pvalloc before or during init\n"); + exit(1); + } + + align_up_size(&size); + void* ptr = next_pvalloc(size); + return ptr; +} + +void* +aligned_alloc(size_t alignment, size_t size) +{ + if (next_aligned_alloc == NULL) { + fprintf(stderr, "called aligned_alloc before or during init\n"); + exit(1); + } + + align_up_size(&size); + void* ptr = next_aligned_alloc(alignment, size); + return ptr; +} + +int +malloc_stats() +{ + if (next_malloc_stats == NULL) { + fprintf(stderr, "called malloc_stats before or during init\n"); + exit(1); + } + + fprintf(stderr, "align_to_cl by muhq\n"); + return next_malloc_stats(); +} diff --git a/src/allocators/tcmalloc.py b/src/allocators/tcmalloc.py index 24f9b45..7d51bdd 100644 --- a/src/allocators/tcmalloc.py +++ b/src/allocators/tcmalloc.py @@ -16,7 +16,7 @@ # along with allocbench. """TCMalloc definition for allocbench""" -from src.allocator import Allocator +from src.allocator import Allocator, BUILDDIR from src.artifact import GitArtifact @@ -62,11 +62,22 @@ class TCMallocGperftools(Allocator): tcmalloc_gperftools = TCMallocGperftools("TCMalloc-gperftools", - color="xkcd:blue", + color="xkcd:dark blue", version="gperftools-2.7") -tcmalloc_gperftools_nofs = TCMallocGperftools( - "TCMalloc-gperftools-NoFalsesharing", - patches=["{patchdir}/tcmalloc_2.7_no_active_falsesharing.patch"], - version="gperftools-2.7", - color="xkcd:navy") +tcmalloc_gperftools_nofs = TCMallocGperftools("TCMalloc-NoFalsesharing", + patches=["{patchdir}/tcmalloc_2.7_no_active_falsesharing.patch"], + version="gperftools-2.7", + color="xkcd:navy") + +tcmalloc_gperftools_align = TCMallocGperftools("TCMalloc-Aligned", + version="gperftools-2.7", + color="xkcd:light blue") + +tcmalloc_gperftools_align.LD_PRELOAD = f"{BUILDDIR}/align_to_cl.so {tcmalloc_gperftools_align.LD_PRELOAD}" + +tcmalloc_gperftools_cacheline_exclusive = TCMalloc("TCMalloc-Cacheline-Exclusive", + patches=["{patchdir}/tcmalloc_2.7_cacheline_exclusive.patch"], + version="gperftools-2.7", + color="xkcd:royal blue") + diff --git a/src/allocators/tcmalloc/tcmalloc_2.7_cacheline_exclusive.patch b/src/allocators/tcmalloc/tcmalloc_2.7_cacheline_exclusive.patch new file mode 100644 index 0000000..bdd63e3 --- /dev/null +++ b/src/allocators/tcmalloc/tcmalloc_2.7_cacheline_exclusive.patch @@ -0,0 +1,26 @@ +diff --git src/common.cc src/common.cc +index 203afdf..9257518 100644 +--- src/common.cc ++++ src/common.cc +@@ -79,7 +79,7 @@ int AlignmentForSize(size_t size) { + if (size > kMaxSize) { + // Cap alignment at kPageSize for large sizes. + alignment = kPageSize; +- } else if (size >= 128) { ++ } else if (size >= 512) { + // Space wasted due to alignment is at most 1/8, i.e., 12.5%. + alignment = (1 << LgFloor(size)) / 8; + } else if (size >= kMinAlign) { +diff --git a/src/common.h b/src/common.h +index cb45315..4131a13 100644 +--- src/common.h ++++ src/common.h +@@ -61,7 +61,7 @@ typedef uintptr_t Length; + // waste due alignment of 25%. (eg malloc of 24 bytes will get 32 bytes) + static const size_t kMinAlign = 8; + #else +-static const size_t kMinAlign = 16; ++static const size_t kMinAlign = 64; + #endif + + // Using large pages speeds up the execution at a cost of larger memory use. diff --git a/src/allocators/tcmallocs.py b/src/allocators/tcmallocs.py new file mode 100644 index 0000000..46eccda --- /dev/null +++ b/src/allocators/tcmallocs.py @@ -0,0 +1,26 @@ +# Copyright 2018-2019 Florian Fischer <florian.fl.fischer@fau.de> +# +# This file is part of allocbench. +# +# allocbench is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# allocbench is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with allocbench. If not, see <http://www.gnu.org/licenses/>. + +"""Collection containing all glibc variants""" + +import src.allocators.tcmalloc as tcm + + +allocators = [tcm.tcmalloc, + tcm.tcmalloc_gperftools_nofs, + tcm.tcmalloc_gperftools_align, + tcm.tcmalloc_gperftools_cacheline_exclusive] |
