aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/Makefile8
-rw-r--r--src/benchmark.py2
-rw-r--r--src/benchmarks/falsesharing.py46
-rw-r--r--src/benchmarks/mysql.py4
-rw-r--r--src/bump_alloc.h54
-rw-r--r--src/bumpptr_alloc.c40
-rw-r--r--src/bumpptr_alloc_always_align.c171
-rw-r--r--src/bumpptr_alloc_single_tsd.c136
8 files changed, 416 insertions, 45 deletions
diff --git a/src/Makefile b/src/Makefile
index 6a46af9..48b35f9 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -25,6 +25,14 @@ $(OBJDIR)/allocators/bumpptr_alloc.so: bumpptr_alloc.c Makefile
@if test \( ! \( -d $(@D) \) \) ;then mkdir -p $(@D);fi
$(CC) $(LDFLAGS) -shared -DMEMSIZE=$(MEMSIZE) $(CFLAGS) -o $@ $<
+$(OBJDIR)/allocators/bumpptr_alloc_always_align.so: bumpptr_alloc_always_align.c.c Makefile
+ @if test \( ! \( -d $(@D) \) \) ;then mkdir -p $(@D);fi
+ $(CC) $(LDFLAGS) -shared -DMEMSIZE=$(MEMSIZE) $(CFLAGS) -o $@ $<
+
+$(OBJDIR)/allocators/bumpptr_alloc_single_tsd.so: bumpptr_alloc_single_tsd.c.c Makefile
+ @if test \( ! \( -d $(@D) \) \) ;then mkdir -p $(@D);fi
+ $(CC) $(LDFLAGS) -shared -DMEMSIZE=$(MEMSIZE) $(CFLAGS) -o $@ $<
+
$(OBJDIR)/allocators/speedymalloc.so: speedymalloc.c Makefile
@if test \( ! \( -d $(@D) \) \) ;then mkdir -p $(@D);fi
$(CC) $(LDFLAGS) -shared -DMEMSIZE=$(MEMSIZE) $(CFLAGS) -o $@ $<
diff --git a/src/benchmark.py b/src/benchmark.py
index d77b09d..3e2a61c 100644
--- a/src/benchmark.py
+++ b/src/benchmark.py
@@ -667,7 +667,7 @@ class Benchmark:
plt.legend(loc="best")
if not autoticks:
- plt.xticks(x_vals, args[loose_arg])
+ plt.xticks(x_vals, args[loose_arg], rotation=90)
plt.xlabel(eval(xlabel))
plt.ylabel(eval(ylabel))
plt.title(eval(title))
diff --git a/src/benchmarks/falsesharing.py b/src/benchmarks/falsesharing.py
index 93c2fe9..cc5e0e3 100644
--- a/src/benchmarks/falsesharing.py
+++ b/src/benchmarks/falsesharing.py
@@ -53,38 +53,35 @@ class BenchmarkFalsesharing(Benchmark):
result["time"] = TIME_RE.match(stdout).group("time")
def summary(self):
- # Speedup thrash
args = self.results["args"]
nthreads = args["threads"]
allocators = self.results["allocators"]
+ # calculate relevant datapoints: speedup, l1-cache-misses
for bench in self.results["args"]["bench"]:
for allocator in allocators:
- y_vals = []
-
- single_threaded_perm = self.Perm(bench=bench, threads=1)
- single_threaded = np.mean([float(m["time"])
- for m in self.results[allocator][single_threaded_perm]])
+ sequential_perm = self.Perm(bench=bench, threads=1)
for perm in self.iterate_args_fixed({"bench": bench}, args=args):
+ speedup = []
+ l1chache_misses = []
+ for i, measure in enumerate(self.results[allocator][perm]):
+ sequential_time = float(self.results[allocator][sequential_perm][i]["time"])
+ measure["speedup"] = float(measure["time"]) / sequential_time
+ measure["l1chache_misses"] = eval("({L1-dcache-load-misses}/{L1-dcache-loads})*100".format(**measure))
+
+ # delete and recalculate stats
+ del self.results["stats"]
+ self.calc_desc_statistics()
+
+ self.plot_fixed_arg("{speedup}",
+ ylabel="'Speedup'",
+ title="'Speedup: ' + arg + ' ' + str(arg_value)",
+ filepostfix="speedup",
+ autoticks=False,
+ fixed=["bench"])
- data = [float(m["time"]) for m in self.results[allocator][perm]]
-
- speedup = single_threaded / np.mean(data)
- self.results["stats"][allocator][perm]["mean"]["speedup"] = speedup
- y_vals.append(speedup)
-
- plt.plot(nthreads, y_vals, marker='.', linestyle='-',
- label=allocator, color=allocators[allocator]["color"])
-
- plt.legend()
- plt.xlabel("threads")
- plt.ylabel("speedup")
- plt.title(bench + " speedup")
- plt.savefig(f"{self.name}.{bench}.{summary_file_ext}")
- plt.clf()
-
- self.plot_fixed_arg("({L1-dcache-load-misses}/{L1-dcache-loads})*100",
+ self.plot_fixed_arg("{l1chache_misses}",
ylabel="'l1 cache misses in %'",
title="'cache misses: ' + arg + ' ' + str(arg_value)",
filepostfix="l1-misses",
@@ -103,5 +100,8 @@ class BenchmarkFalsesharing(Benchmark):
"sort":">"}],
filepostfix="speedup.table")
+ self.export_stats_to_csv("speedup", "time")
+ self.export_stats_to_csv("l1chache_misses", "l1-misses")
+
falsesharing = BenchmarkFalsesharing()
diff --git a/src/benchmarks/mysql.py b/src/benchmarks/mysql.py
index c7519c5..2889497 100644
--- a/src/benchmarks/mysql.py
+++ b/src/benchmarks/mysql.py
@@ -86,8 +86,8 @@ from src.benchmark import Benchmark
import src.facter
from src.util import print_status, print_debug, print_info2
-MYSQL_USER = "root"
-RUN_TIME = 300
+MYSQL_USER = "fischerling"
+RUN_TIME = 10
TABLES = 5
PREPARE_CMD = (f"sysbench oltp_read_only --db-driver=mysql --mysql-user={MYSQL_USER} "
diff --git a/src/bump_alloc.h b/src/bump_alloc.h
new file mode 100644
index 0000000..bc9cbac
--- /dev/null
+++ b/src/bump_alloc.h
@@ -0,0 +1,54 @@
+#include <assert.h>
+#include <stddef.h> /* NULL, size_t */
+#include <stdint.h> /* uintptr_t */
+
+#ifndef MEMSIZE
+#define MEMSIZE 1024*4*1024*1024l
+#endif
+
+#define unlikely(x) __builtin_expect((x),0)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct {
+ uintptr_t end = 0;
+ uintptr_t ptr = 0;
+} bumpptr_t;
+
+__thread bumpptr_t* tsd = NULL;
+
+inline void init_tsd() {
+ void* mem_start = mmap(NULL, MEMSIZE, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
+ if(mem_start == MAP_FAILED) {
+ perror("mmap");
+ return NULL;
+ }
+ tsd = (bumpptr_t*)mem_start;
+ tsd->ptr = (uintptr_t)mem_start + sizeof(bumpptr_t);
+ tsd->end = (uintptr_t)mem_start + MEMSIZE;
+}
+
+inline void* bump_up(size_t size, size_t align) {
+ assert(align % 2 == 0);
+
+ if (unlikely(tsd == NULL)) {
+ init_tsd();
+ }
+
+ // align ptr;
+ uintptr_t aligned = (tsd->ptr + align - 1) & ~(align - 1);
+
+ uintptr_t new_ptr = aligned + size;
+ if (new_ptr > mem_end)
+ return NULL;
+ else {
+ tsd->ptr = new_ptr;
+ return (void*)aligned;
+ }
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/src/bumpptr_alloc.c b/src/bumpptr_alloc.c
index 3985904..6cb82df 100644
--- a/src/bumpptr_alloc.c
+++ b/src/bumpptr_alloc.c
@@ -1,3 +1,4 @@
+#include <assert.h>
#include <errno.h>
#include <stddef.h> /* NULL, size_t */
#include <stdint.h> /* uintptr_t */
@@ -19,11 +20,12 @@ extern "C" {
#endif
__thread void* mem_start = NULL;
-__thread void* mem_end = NULL;
-
+__thread uintptr_t mem_end = 0;
__thread uintptr_t ptr = 0;
-void* malloc(size_t size) {
+inline void* bump_up(size_t size, size_t align) {
+ assert(align % 2 == 0);
+
if (unlikely(mem_start == NULL)) {
mem_start = mmap(NULL, MEMSIZE, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
if(mem_start == MAP_FAILED) {
@@ -31,17 +33,23 @@ void* malloc(size_t size) {
return NULL;
}
ptr = (uintptr_t)mem_start;
+ mem_end = ptr + MEMSIZE;
}
// align ptr;
- if (ptr % MIN_ALIGNMENT != 0) {
- size_t mask = MIN_ALIGNMENT -1;
- ptr = (ptr + mask) & ~mask;
+ uintptr_t aligned = (ptr + align - 1) & ~(align - 1);
+
+ uintptr_t new_ptr = aligned + size;
+ if (new_ptr > mem_end)
+ return NULL;
+ else {
+ ptr = new_ptr;
+ return (void*)aligned;
}
+}
- void* ret = (void*)ptr;
- ptr += size;
- return ret;
+void* malloc(size_t size) {
+ return bump_up(size, MIN_ALIGNMENT);
}
void free(__attribute__ ((unused)) void* ptr) {
@@ -51,20 +59,14 @@ void* realloc(void* ptr, size_t size) {
if(ptr == NULL)
return malloc(size);
- if(size == 0)
- return NULL;
-
- void* new_ptr = malloc(size);
+ void* new_ptr = bump_up(size, MIN_ALIGNMENT);
// this may copies to much
memcpy(new_ptr, ptr, size);
return new_ptr;
}
void* memalign(size_t alignment, size_t size) {
- // align ptr to alignment and malloc
- size_t mask = alignment - 1;
- ptr = (ptr + mask) & ~mask;
- return malloc(size);
+ return bump_up(size, alignment);
}
int posix_memalign(void **memptr, size_t alignment, size_t size)
@@ -89,7 +91,7 @@ int posix_memalign(void **memptr, size_t alignment, size_t size)
return 0;
}
- out = memalign(alignment, size);
+ out = bump_up(size, alignment);
if(out == NULL) {
return 12;
}
@@ -107,7 +109,7 @@ void* calloc(size_t nmemb, size_t size)
return NULL;
}
- out = malloc(fullsize);
+ out = bump_up(fullsize, MIN_ALIGNMENT);
if(out == NULL) {
return NULL;
}
diff --git a/src/bumpptr_alloc_always_align.c b/src/bumpptr_alloc_always_align.c
new file mode 100644
index 0000000..6cb82df
--- /dev/null
+++ b/src/bumpptr_alloc_always_align.c
@@ -0,0 +1,171 @@
+#include <assert.h>
+#include <errno.h>
+#include <stddef.h> /* NULL, size_t */
+#include <stdint.h> /* uintptr_t */
+#include <stdio.h> /* uintptr_t */
+#include <unistd.h> /* sysconf(_SC_PAGESIZE) */
+#include <string.h> /* memset */
+#include <sys/mman.h> /* memset */
+
+#define MIN_ALIGNMENT 16
+
+#ifndef MEMSIZE
+#define MEMSIZE 1024*4*1024*1024l
+#endif
+
+#define unlikely(x) __builtin_expect((x),0)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+__thread void* mem_start = NULL;
+__thread uintptr_t mem_end = 0;
+__thread uintptr_t ptr = 0;
+
+inline void* bump_up(size_t size, size_t align) {
+ assert(align % 2 == 0);
+
+ if (unlikely(mem_start == NULL)) {
+ mem_start = mmap(NULL, MEMSIZE, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
+ if(mem_start == MAP_FAILED) {
+ perror("mmap");
+ return NULL;
+ }
+ ptr = (uintptr_t)mem_start;
+ mem_end = ptr + MEMSIZE;
+ }
+
+ // align ptr;
+ uintptr_t aligned = (ptr + align - 1) & ~(align - 1);
+
+ uintptr_t new_ptr = aligned + size;
+ if (new_ptr > mem_end)
+ return NULL;
+ else {
+ ptr = new_ptr;
+ return (void*)aligned;
+ }
+}
+
+void* malloc(size_t size) {
+ return bump_up(size, MIN_ALIGNMENT);
+}
+
+void free(__attribute__ ((unused)) void* ptr) {
+}
+
+void* realloc(void* ptr, size_t size) {
+ if(ptr == NULL)
+ return malloc(size);
+
+ void* new_ptr = bump_up(size, MIN_ALIGNMENT);
+ // this may copies to much
+ memcpy(new_ptr, ptr, size);
+ return new_ptr;
+}
+
+void* memalign(size_t alignment, size_t size) {
+ return bump_up(size, alignment);
+}
+
+int posix_memalign(void **memptr, size_t alignment, size_t size)
+{
+ void *out;
+
+ if(memptr == NULL) {
+ return 22;
+ }
+
+ if((alignment % sizeof(void*)) != 0) {
+ return 22;
+ }
+
+ /* if not power of two */
+ if(!((alignment != 0) && !(alignment & (alignment - 1)))) {
+ return 22;
+ }
+
+ if(size == 0) {
+ *memptr = NULL;
+ return 0;
+ }
+
+ out = bump_up(size, alignment);
+ if(out == NULL) {
+ return 12;
+ }
+
+ *memptr = out;
+ return 0;
+}
+
+void* calloc(size_t nmemb, size_t size)
+{
+ void *out;
+ size_t fullsize = nmemb * size;
+
+ if((size != 0) && ((fullsize / size) != nmemb)) {
+ return NULL;
+ }
+
+ out = bump_up(fullsize, MIN_ALIGNMENT);
+ if(out == NULL) {
+ return NULL;
+ }
+
+ memset(out, 0, fullsize);
+ return out;
+}
+
+void* valloc(size_t size)
+{
+ long ret = sysconf(_SC_PAGESIZE);
+ if(ret == -1) {
+ return NULL;
+ }
+
+ return memalign(ret, size);
+}
+
+void* pvalloc(size_t size)
+{
+ size_t ps, rem, allocsize;
+
+ long ret = sysconf(_SC_PAGESIZE);
+ if(ret == -1) {
+ return NULL;
+ }
+
+ ps = ret;
+ rem = size % ps;
+ allocsize = size;
+ if(rem != 0) {
+ allocsize = ps + (size - rem);
+ }
+
+ return memalign(ps, allocsize);
+}
+
+void* aligned_alloc(size_t alignment, size_t size)
+{
+ if(alignment > size) {
+ return NULL;
+ }
+
+ if((size % alignment) != 0) {
+ return NULL;
+ }
+
+ return memalign(alignment, size);
+}
+
+int malloc_stats() {
+ fprintf(stderr, "Bump pointer allocator by muhq\n");
+ fprintf(stderr, "Memsize: %zu, start address: %p, bump pointer %p\n", MEMSIZE, mem_start, ptr);
+ return 0;
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/src/bumpptr_alloc_single_tsd.c b/src/bumpptr_alloc_single_tsd.c
new file mode 100644
index 0000000..7c51bae
--- /dev/null
+++ b/src/bumpptr_alloc_single_tsd.c
@@ -0,0 +1,136 @@
+#include <errno.h> /* TODO: set errno */
+#include <stddef.h> /* NULL, size_t */
+#include <stdint.h> /* uintptr_t */
+#include <stdio.h> /* fprintf */
+#include <unistd.h> /* sysconf(_SC_PAGESIZE) */
+#include <string.h> /* memset */
+
+#include "bump_alloc.h"
+
+#define MIN_ALIGNMENT 16
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void* malloc(size_t size) {
+ return bump_up(size, MIN_ALIGNMENT);
+}
+
+void free(__attribute__ ((unused)) void* ptr) {
+}
+
+void* realloc(void* ptr, size_t size) {
+ if(ptr == NULL)
+ return malloc(size);
+
+ void* new_ptr = bump_up(size, MIN_ALIGNMENT);
+ // this may copies to much
+ memcpy(new_ptr, ptr, size);
+ return new_ptr;
+}
+
+void* memalign(size_t alignment, size_t size) {
+ return bump_up(size, alignment);
+}
+
+int posix_memalign(void **memptr, size_t alignment, size_t size)
+{
+ void *out;
+
+ if(memptr == NULL) {
+ return 22;
+ }
+
+ if((alignment % sizeof(void*)) != 0) {
+ return 22;
+ }
+
+ /* if not power of two */
+ if(!((alignment != 0) && !(alignment & (alignment - 1)))) {
+ return 22;
+ }
+
+ if(size == 0) {
+ *memptr = NULL;
+ return 0;
+ }
+
+ out = bump_up(size, alignment);
+ if(out == NULL) {
+ return 12;
+ }
+
+ *memptr = out;
+ return 0;
+}
+
+void* calloc(size_t nmemb, size_t size)
+{
+ void *out;
+ size_t fullsize = nmemb * size;
+
+ if((size != 0) && ((fullsize / size) != nmemb)) {
+ return NULL;
+ }
+
+ out = bump_up(fullsize, MIN_ALIGNMENT);
+ if(out == NULL) {
+ return NULL;
+ }
+
+ memset(out, 0, fullsize);
+ return out;
+}
+
+void* valloc(size_t size)
+{
+ long ret = sysconf(_SC_PAGESIZE);
+ if(ret == -1) {
+ return NULL;
+ }
+
+ return memalign(ret, size);
+}
+
+void* pvalloc(size_t size)
+{
+ size_t ps, rem, allocsize;
+
+ long ret = sysconf(_SC_PAGESIZE);
+ if(ret == -1) {
+ return NULL;
+ }
+
+ ps = ret;
+ rem = size % ps;
+ allocsize = size;
+ if(rem != 0) {
+ allocsize = ps + (size - rem);
+ }
+
+ return memalign(ps, allocsize);
+}
+
+void* aligned_alloc(size_t alignment, size_t size)
+{
+ if(alignment > size) {
+ return NULL;
+ }
+
+ if((size % alignment) != 0) {
+ return NULL;
+ }
+
+ return memalign(alignment, size);
+}
+
+int malloc_stats() {
+ fprintf(stderr, "Bump pointer allocator by muhq\n");
+ fprintf(stderr, "Memsize: %zu, start address: %p, bump pointer %p\n", MEMSIZE, mem_start, ptr);
+ return 0;
+}
+
+#ifdef __cplusplus
+}
+#endif