aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/benchmarks/t_test1.py53
-rw-r--r--src/benchmarks/t_test1/Makefile37
-rw-r--r--src/benchmarks/t_test1/lran2.h51
-rw-r--r--src/benchmarks/t_test1/t-test.h143
-rw-r--r--src/benchmarks/t_test1/t-test1.c401
5 files changed, 685 insertions, 0 deletions
diff --git a/src/benchmarks/t_test1.py b/src/benchmarks/t_test1.py
new file mode 100644
index 0000000..e43a511
--- /dev/null
+++ b/src/benchmarks/t_test1.py
@@ -0,0 +1,53 @@
+from src.allocator import bumpptr
+from src.benchmark import Benchmark
+
+
+class Benchmark_t_test1(Benchmark):
+ def __init__(self):
+ self.name = "t_test1"
+ self.descrition = """This benchmark from ptmalloc2 allocates and frees
+ n bins in t concurrent threads."""
+
+ self.cmd = "t-test1 {nthreads} {nthreads} 1000000 {maxsize}"
+
+ self.args = {"maxsize": [2 ** x for x in range(6, 18)],
+ "nthreads": Benchmark.scale_threads_for_cpus(2)}
+
+ self.requirements = ["t-test1"]
+ super().__init__()
+
+ self.allocators["bumpptr"] = bumpptr.build()
+
+ def summary(self):
+ # mops / per second
+ yval = "perm.nthreads / ({task-clock}/1000)"
+ # Speed
+ self.plot_fixed_arg(yval,
+ ylabel='"Mops / CPU second"',
+ title='"T-Ttest1: " + arg + " " + str(arg_value)',
+ filepostfix="time",
+ autoticks=False)
+
+ scale = list(self.results["allocators"].keys())[0]
+ self.plot_fixed_arg(yval,
+ ylabel='"Mops / CPU second scaled at {}"'.format(scale),
+ title='"T-Test1: " + arg + " " + str(arg_value) + " normalized {}"'.format(scale),
+ filepostfix="time.norm",
+ scale=scale,
+ autoticks=False)
+
+ # L1 cache misses
+ self.plot_fixed_arg("({L1-dcache-load-misses}/{L1-dcache-loads})*100",
+ ylabel='"L1 misses in %"',
+ title='"T-Test1 l1 cache misses: " + arg + " " + str(arg_value)',
+ filepostfix="l1misses",
+ autoticks=False)
+
+ # Speed Matrix
+ self.write_best_doublearg_tex_table(yval,
+ filepostfix="memusage.matrix")
+
+ self.export_to_csv("task-clock")
+
+
+t_test1 = Benchmark_t_test1()
diff --git a/src/benchmarks/t_test1/Makefile b/src/benchmarks/t_test1/Makefile
new file mode 100644
index 0000000..109e9a6
--- /dev/null
+++ b/src/benchmarks/t_test1/Makefile
@@ -0,0 +1,37 @@
+# Makefile for t-test1 from ptmalloc, version 2
+# by Florian Fischer 2019
+# derived from
+# Makefile for ptmalloc, version 2
+# by Wolfram Gloger 1996-1999, 2001, 2002, 2003, 2004, 2006
+
+OBJDIR ?= obj
+
+CC ?= cc
+
+SYS_FLAGS = -D_GNU_SOURCE=1
+OPT_FLAGS ?= -g -O # -O2
+WARN_FLAGS ?= -Wall -Wstrict-prototypes
+
+# Flags for the test programs
+T_FLAGS = -DTEST=1
+
+# Thread flags.
+# See the platform-specific targets below.
+THR_FLAGS = -DUSE_TSD_DATA_HACK -D_REENTRANT
+THR_LIBS = -lpthread
+
+RM = rm -f
+
+CFLAGS ?= $(SYS_FLAGS) $(OPT_FLAGS) $(WARN_FLAGS) $(THR_FLAGS)
+
+all: $(OBJDIR)/t-test1
+
+$(OBJDIR)/t-test1: t-test1.c t-test.h | $(OBJDIR)
+ @echo compiling $@
+ $(CC) $(CFLAGS) $(T_FLAGS) t-test1.c $(THR_LIBS) -o $@
+
+$(OBJDIR):
+ mkdir -p $@
+
+clean:
+ $(RM) -rf $(OBJDIR)
diff --git a/src/benchmarks/t_test1/lran2.h b/src/benchmarks/t_test1/lran2.h
new file mode 100644
index 0000000..cea9920
--- /dev/null
+++ b/src/benchmarks/t_test1/lran2.h
@@ -0,0 +1,51 @@
+/* lran2.h
+ * by Wolfram Gloger 1996.
+ *
+ * A small, portable pseudo-random number generator.
+ */
+
+#ifndef _LRAN2_H
+#define _LRAN2_H
+
+#define LRAN2_MAX 714025l /* constants for portable */
+#define IA 1366l /* random number generator */
+#define IC 150889l /* (see e.g. `Numerical Recipes') */
+
+struct lran2_st {
+ long x, y, v[97];
+};
+
+static void
+lran2_init(struct lran2_st* d, long seed)
+{
+ long x;
+ int j;
+
+ x = (IC - seed) % LRAN2_MAX;
+ if(x < 0) x = -x;
+ for(j=0; j<97; j++) {
+ x = (IA*x + IC) % LRAN2_MAX;
+ d->v[j] = x;
+ }
+ d->x = (IA*x + IC) % LRAN2_MAX;
+ d->y = d->x;
+}
+
+#ifdef __GNUC__
+__inline__
+#endif
+static long
+lran2(struct lran2_st* d)
+{
+ int j = (d->y % 97);
+
+ d->y = d->v[j];
+ d->x = (IA*d->x + IC) % LRAN2_MAX;
+ d->v[j] = d->x;
+ return d->y;
+}
+
+#undef IA
+#undef IC
+
+#endif
diff --git a/src/benchmarks/t_test1/t-test.h b/src/benchmarks/t_test1/t-test.h
new file mode 100644
index 0000000..a52829a
--- /dev/null
+++ b/src/benchmarks/t_test1/t-test.h
@@ -0,0 +1,143 @@
+/*
+ * $Id: t-test.h,v 1.1 2004/11/04 14:32:21 wg Exp $
+ * by Wolfram Gloger 1996.
+ * Common data structures and functions for testing malloc performance.
+ */
+
+/* Testing level */
+#ifndef TEST
+#define TEST 0
+#endif
+
+/* For large allocation sizes, the time required by copying in
+ realloc() can dwarf all other execution times. Avoid this with a
+ size threshold. */
+#ifndef REALLOC_MAX
+#define REALLOC_MAX 2000
+#endif
+
+struct bin {
+ unsigned char *ptr;
+ unsigned long size;
+};
+
+#if TEST > 0
+
+static void
+mem_init(unsigned char *ptr, unsigned long size)
+{
+ unsigned long i, j;
+
+ if(size == 0) return;
+ for(i=0; i<size; i+=2047) {
+ j = (unsigned long)ptr ^ i;
+ ptr[i] = ((j ^ (j>>8)) & 0xFF);
+ }
+ j = (unsigned long)ptr ^ (size-1);
+ ptr[size-1] = ((j ^ (j>>8)) & 0xFF);
+}
+
+static int
+mem_check(unsigned char *ptr, unsigned long size)
+{
+ unsigned long i, j;
+
+ if(size == 0) return 0;
+ for(i=0; i<size; i+=2047) {
+ j = (unsigned long)ptr ^ i;
+ if(ptr[i] != ((j ^ (j>>8)) & 0xFF)) return 1;
+ }
+ j = (unsigned long)ptr ^ (size-1);
+ if(ptr[size-1] != ((j ^ (j>>8)) & 0xFF)) return 2;
+ return 0;
+}
+
+static int
+zero_check(unsigned* ptr, unsigned long size)
+{
+ unsigned char* ptr2;
+
+ while(size >= sizeof(*ptr)) {
+ if(*ptr++ != 0)
+ return -1;
+ size -= sizeof(*ptr);
+ }
+ ptr2 = (unsigned char*)ptr;
+ while(size > 0) {
+ if(*ptr2++ != 0)
+ return -1;
+ --size;
+ }
+ return 0;
+}
+
+#endif /* TEST > 0 */
+
+/* Allocate a bin with malloc(), realloc() or memalign(). r must be a
+ random number >= 1024. */
+
+static void
+bin_alloc(struct bin *m, unsigned long size, int r)
+{
+#if TEST > 0
+ if(mem_check(m->ptr, m->size)) {
+ printf("memory corrupt!\n");
+ exit(1);
+ }
+#endif
+ r %= 1024;
+ /*printf("%d ", r);*/
+ if(r < 4) { /* memalign */
+ if(m->size > 0) free(m->ptr);
+ m->ptr = (unsigned char *)memalign(sizeof(int) << r, size);
+ } else if(r < 20) { /* calloc */
+ if(m->size > 0) free(m->ptr);
+ m->ptr = (unsigned char *)calloc(size, 1);
+#if TEST > 0
+ if(zero_check((unsigned*)m->ptr, size)) {
+ long i;
+ for(i=0; i<size; i++)
+ if(m->ptr[i] != 0)
+ break;
+ printf("calloc'ed memory non-zero (ptr=%p, i=%ld)!\n", m->ptr, i);
+ exit(1);
+ }
+#endif
+ } else if(r < 100 && m->size < REALLOC_MAX) { /* realloc */
+ if(m->size == 0) m->ptr = NULL;
+ m->ptr = realloc(m->ptr, size);
+ } else { /* plain malloc */
+ if(m->size > 0) free(m->ptr);
+ m->ptr = (unsigned char *)malloc(size);
+ }
+ if(!m->ptr) {
+ printf("out of memory (r=%d, size=%ld)!\n", r, (long)size);
+ exit(1);
+ }
+ m->size = size;
+#if TEST > 0
+ mem_init(m->ptr, m->size);
+#endif
+}
+
+/* Free a bin. */
+
+static void
+bin_free(struct bin *m)
+{
+ if(m->size == 0) return;
+#if TEST > 0
+ if(mem_check(m->ptr, m->size)) {
+ printf("memory corrupt!\n");
+ exit(1);
+ }
+#endif
+ free(m->ptr);
+ m->size = 0;
+}
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * End:
+ */
diff --git a/src/benchmarks/t_test1/t-test1.c b/src/benchmarks/t_test1/t-test1.c
new file mode 100644
index 0000000..86eb034
--- /dev/null
+++ b/src/benchmarks/t_test1/t-test1.c
@@ -0,0 +1,401 @@
+/*
+ * $Id: t-test1.c,v 1.1.1.1 2003/07/02 16:32:09 matthias.urban Exp $
+ * by Wolfram Gloger 1996-1999
+ * A multi-thread test for malloc performance, maintaining one pool of
+ * allocated bins per thread.
+ *
+ * Fixed condition variable usage, and ported to windows
+ * Steven Fuerst 2009
+ */
+
+/* Testing level */
+#ifndef TEST
+#define TEST 0
+#endif
+
+#define N_TOTAL 500
+#ifndef N_THREADS
+#define N_THREADS 2
+#endif
+#ifndef N_TOTAL_PRINT
+#define N_TOTAL_PRINT 50
+#endif
+#define STACKSIZE 32768
+#ifndef MEMORY
+#define MEMORY (1ULL << 26)
+#endif
+
+#define RANDOM(s) (rng() % (s))
+
+#define MSIZE 10000
+#define I_MAX 10000
+#define ACTIONS_MAX 30
+
+#include <pthread.h>
+
+#if (defined __STDC__ && __STDC__) || defined __cplusplus
+# include <stdlib.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef __GCC__
+#include <unistd.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/wait.h>
+#endif
+
+#include <sys/types.h>
+#include <malloc.h>
+
+
+/*
+ * Ultra-fast RNG: Use a fast hash of integers.
+ * 2**64 Period.
+ * Passes Diehard and TestU01 at maximum settings
+ */
+static __thread unsigned long long rnd_seed;
+
+static inline unsigned rng(void)
+{
+ unsigned long long c = 7319936632422683443ULL;
+ unsigned long long x = (rnd_seed += c);
+
+ x ^= x >> 32;
+ x *= c;
+ x ^= x >> 32;
+ x *= c;
+ x ^= x >> 32;
+
+ /* Return lower 32bits */
+ return x;
+}
+
+/* For large allocation sizes, the time required by copying in
+ realloc() can dwarf all other execution times. Avoid this with a
+ size threshold. */
+#ifndef REALLOC_MAX
+#define REALLOC_MAX 2000
+#endif
+
+struct bin
+{
+ unsigned char *ptr;
+ size_t size;
+};
+
+static pthread_cond_t finish_cond;
+static pthread_mutex_t finish_mutex;
+
+#if TEST > 0
+
+static void mem_init(unsigned char *ptr, size_t size)
+{
+ size_t i, j;
+
+ if (!size) return;
+ for (i = 0; i < size; i += 2047)
+ {
+ j = (size_t)ptr ^ i;
+ ptr[i] = j ^ (j>>8);
+ }
+ j = (size_t)ptr ^ (size - 1);
+ ptr[size-1] = j ^ (j>>8);
+}
+
+static int mem_check(unsigned char *ptr, size_t size)
+{
+ size_t i, j;
+
+ if (!size) return 0;
+ for (i = 0; i < size; i += 2047)
+ {
+ j = (size_t)ptr ^ i;
+ if (ptr[i] != ((j ^ (j>>8)) & 0xFF)) return 1;
+ }
+ j = (size_t)ptr ^ (size - 1);
+ if (ptr[size-1] != ((j ^ (j>>8)) & 0xFF)) return 2;
+ return 0;
+}
+
+static int zero_check(void *p, size_t size)
+{
+ unsigned *ptr = p;
+ unsigned char *ptr2;
+
+ while (size >= sizeof(*ptr))
+ {
+ if (*ptr++) return -1;
+ size -= sizeof(*ptr);
+ }
+ ptr2 = (unsigned char*)ptr;
+
+ while (size > 0)
+ {
+ if (*ptr2++) return -1;
+ --size;
+ }
+ return 0;
+}
+
+#endif /* TEST > 0 */
+
+/*
+ * Allocate a bin with malloc(), realloc() or memalign().
+ * r must be a random number >= 1024.
+ */
+static void bin_alloc(struct bin *m, size_t size, unsigned r)
+{
+#if TEST > 0
+ if (mem_check(m->ptr, m->size))
+ {
+ printf("memory corrupt!\n");
+ exit(1);
+ }
+#endif
+ r %= 1024;
+
+ if (r < 4)
+ {
+ /* memalign */
+ if (m->size > 0) free(m->ptr);
+ m->ptr = memalign(sizeof(int) << r, size);
+ }
+ else if (r < 20)
+ {
+ /* calloc */
+ if (m->size > 0) free(m->ptr);
+ m->ptr = calloc(size, 1);
+#if TEST > 0
+ if (zero_check(m->ptr, size))
+ {
+ size_t i;
+ for (i = 0; i < size; i++)
+ {
+ if (m->ptr[i]) break;
+ }
+ printf("calloc'ed memory non-zero (ptr=%p, i=%ld)!\n", m->ptr, i);
+ exit(1);
+ }
+#endif
+ }
+ else if ((r < 100) && (m->size < REALLOC_MAX))
+ {
+ /* realloc */
+ if (!m->size) m->ptr = NULL;
+ m->ptr = realloc(m->ptr, size);
+ }
+ else
+ {
+ /* malloc */
+ if (m->size > 0) free(m->ptr);
+ m->ptr = malloc(size);
+ }
+ if (!m->ptr)
+ {
+ printf("out of memory (r=%d, size=%ld)!\n", r, (unsigned long)size);
+ exit(1);
+ }
+
+ m->size = size;
+#if TEST > 0
+ mem_init(m->ptr, m->size);
+#endif
+}
+
+/* Free a bin. */
+
+static void bin_free(struct bin *m)
+{
+ if (!m->size) return;
+
+#if TEST > 0
+ if (mem_check(m->ptr, m->size))
+ {
+ printf("memory corrupt!\n");
+ exit(1);
+ }
+#endif
+
+ free(m->ptr);
+ m->size = 0;
+}
+
+struct bin_info
+{
+ struct bin *m;
+ size_t size, bins;
+};
+
+struct thread_st
+{
+ int bins, max, flags;
+ size_t size;
+ pthread_t id;
+ char *sp;
+ size_t seed;
+};
+
+static void *malloc_test(void *ptr)
+{
+ struct thread_st *st = ptr;
+ int i, pid = 1;
+ unsigned b, j, actions;
+ struct bin_info p;
+
+ rnd_seed = st->seed;
+
+ p.m = malloc(st->bins * sizeof(*p.m));
+ p.bins = st->bins;
+ p.size = st->size;
+ for (b = 0; b < p.bins; b++)
+ {
+ p.m[b].size = 0;
+ p.m[b].ptr = NULL;
+ if (!RANDOM(2)) bin_alloc(&p.m[b], RANDOM(p.size) + 1, rng());
+ }
+
+ for (i = 0; i <= st->max;)
+ {
+ actions = RANDOM(ACTIONS_MAX);
+
+ for (j = 0; j < actions; j++)
+ {
+ b = RANDOM(p.bins);
+ bin_free(&p.m[b]);
+ }
+ i += actions;
+ actions = RANDOM(ACTIONS_MAX);
+
+ for (j = 0; j < actions; j++)
+ {
+ b = RANDOM(p.bins);
+ bin_alloc(&p.m[b], RANDOM(p.size) + 1, rng());
+ }
+
+ i += actions;
+ }
+
+ for (b = 0; b < p.bins; b++) bin_free(&p.m[b]);
+
+ free(p.m);
+
+ if (pid > 0)
+ {
+ pthread_mutex_lock(&finish_mutex);
+ st->flags = 1;
+ pthread_cond_signal(&finish_cond);
+ pthread_mutex_unlock(&finish_mutex);
+ }
+ return NULL;
+}
+
+static int my_start_thread(struct thread_st *st)
+{
+ pthread_create(&st->id, NULL, malloc_test, st);
+ return 0;
+}
+
+static int n_total = 0;
+static int n_total_max = N_TOTAL;
+static int n_running;
+
+static int my_end_thread(struct thread_st *st)
+{
+ /* Thread st has finished. Start a new one. */
+ if (n_total >= n_total_max)
+ {
+ n_running--;
+ }
+ else if (st->seed++, my_start_thread(st))
+ {
+ printf("Creating thread #%d failed.\n", n_total);
+ }
+ else
+ {
+ n_total++;
+ if (!(n_total%N_TOTAL_PRINT)) printf("n_total = %d\n", n_total);
+ }
+ return 0;
+}
+
+int main(int argc, char *argv[])
+{
+ int i, bins;
+ int n_thr = N_THREADS;
+ int i_max = I_MAX;
+ size_t size = MSIZE;
+ struct thread_st *st;
+
+ if (argc > 1) n_total_max = atoi(argv[1]);
+ if (n_total_max < 1) n_thr = 1;
+ if (argc > 2) n_thr = atoi(argv[2]);
+ if (n_thr < 1) n_thr = 1;
+ if (n_thr > 100) n_thr = 100;
+ if (argc > 3) i_max = atoi(argv[3]);
+
+ if (argc > 4) size = atol(argv[4]);
+ if (size < 2) size = 2;
+
+ bins = MEMORY /(size * n_thr);
+ if (argc > 5) bins = atoi(argv[5]);
+ if (bins < 4) bins = 4;
+
+ printf("Using posix threads.\n");
+ pthread_cond_init(&finish_cond, NULL);
+ pthread_mutex_init(&finish_mutex, NULL);
+
+ printf("total=%d threads=%d i_max=%d size=%ld bins=%d\n",
+ n_total_max, n_thr, i_max, size, bins);
+
+ st = malloc(n_thr * sizeof(*st));
+ if (!st) exit(-1);
+
+ pthread_mutex_lock(&finish_mutex);
+
+ /* Start all n_thr threads. */
+ for (i = 0; i < n_thr; i++)
+ {
+ st[i].bins = bins;
+ st[i].max = i_max;
+ st[i].size = size;
+ st[i].flags = 0;
+ st[i].sp = 0;
+ st[i].seed = (i_max * size + i) ^ bins;
+ if (my_start_thread(&st[i]))
+ {
+ printf("Creating thread #%d failed.\n", i);
+ n_thr = i;
+ break;
+ }
+ printf("Created thread %lx.\n", (long)st[i].id);
+ }
+
+ for (n_running = n_total = n_thr; n_running > 0;)
+ {
+
+ /* Wait for subthreads to finish. */
+ pthread_cond_wait(&finish_cond, &finish_mutex);
+ for (i = 0; i < n_thr; i++)
+ {
+ if (st[i].flags)
+ {
+ pthread_join(st[i].id, NULL);
+ st[i].flags = 0;
+ my_end_thread(&st[i]);
+ }
+ }
+ }
+ pthread_mutex_unlock(&finish_mutex);
+
+ for (i = 0; i < n_thr; i++)
+ {
+ if (st[i].sp) free(st[i].sp);
+ }
+ free(st);
+ malloc_stats();
+ printf("Done.\n");
+ return 0;
+}
+