diff --git a/src/benchmarks/t_test1.py b/src/benchmarks/t_test1.py
new file mode 100644
index 0000000000000000000000000000000000000000..e43a511befd3b72ca5714ae85cbd73fa5fe35dea
--- /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 0000000000000000000000000000000000000000..109e9a607ac3ca4ca9acedade5b651d195556e8e
--- /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 0000000000000000000000000000000000000000..cea9920282a70e191b95faa6bbc3f9fa0d0138a0
--- /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 0000000000000000000000000000000000000000..a52829a41d3efe8b55bf0f286f15b4489115ba8a
--- /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 0000000000000000000000000000000000000000..86eb034944516818633333649bbfa47178d993b9
--- /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;
+}
+