aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/Makefile6
-rw-r--r--src/align_to_cl.c240
-rw-r--r--src/allocators/tcmalloc.py25
-rw-r--r--src/allocators/tcmalloc/tcmalloc_2.7_cacheline_exclusive.patch26
-rw-r--r--src/allocators/tcmallocs.py26
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]