aboutsummaryrefslogtreecommitdiff
path: root/src/benchmarks/t_test1/t-test1.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/benchmarks/t_test1/t-test1.c')
-rw-r--r--src/benchmarks/t_test1/t-test1.c401
1 files changed, 401 insertions, 0 deletions
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;
+}
+