Skip to content

Commit

Permalink
Merge pull request #40 from dryman/OPIC-34
Browse files Browse the repository at this point in the history
OPIC-34 massive malloc/free on opic malloc
  • Loading branch information
dryman authored Mar 27, 2017
2 parents a219873 + daa5dfa commit 7cb2f28
Show file tree
Hide file tree
Showing 9 changed files with 329 additions and 6 deletions.
2 changes: 1 addition & 1 deletion Makefile.am
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
SUBDIRS = opic
SUBDIRS = opic benchmark

nobase_include_HEADERS = \
opic/op_malloc.h \
Expand Down
26 changes: 26 additions & 0 deletions benchmark/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
TLSF-BSD is freely redistributable under the two-clause BSD License:

Copyright (c) 2016 National Cheng Kung University, Taiwan.
Copyright (c) 2006-2008, 2011, 2014 Matthew Conte.
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
*
THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
5 changes: 5 additions & 0 deletions benchmark/Makefile.am
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
bin_PROGRAMS = malloc_bench

malloc_bench_SOURCES = malloc_bench.c
malloc_bench_LDADD = $(top_builddir)/opic/libdemomalloc.la @PTHREAD_LIBS@ @atomic_LIBS@
malloc_bench_LDFLAGS = -static
44 changes: 44 additions & 0 deletions benchmark/lran2.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/* Copyright (c) 1996 Wolfram Gloger.
* 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 inline
void lran2_init(struct lran2_st *d, long seed)
{
long x = (IC - seed) % LRAN2_MAX;
if (x < 0)
x = -x;
for (int 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;
}

static inline
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
240 changes: 240 additions & 0 deletions benchmark/malloc_bench.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,240 @@
/* Copyright (c) 2016 National Cheng Kung University, Taiwan.
* All rights reserved.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/

#ifndef _DEFAULT_SOURCE
#define _DEFAULT_SOURCE
#endif
#define _POSIX_C_SOURCE 199309L

#include <unistd.h>
#include <assert.h>
#include <errno.h>
#include <sched.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <time.h>

#include "lran2.h"
#include "opic/op_malloc.h"

static OPHeap* heap;
#ifdef DEBUG
static int counter;
#endif

static void usage(const char *name)
{
printf("run a malloc benchmark.\n"
"usage: %s [-s blk-size|blk-min:blk-max] [-l loop-count] "
"[-n num-blocks] [-c]\n",
name);
exit(-1);
}

/* Parse an integer argument. */
static int parse_int_arg(const char *arg, const char *exe_name)
{
long int ret;

errno = 0;
ret = strtol(arg, NULL, 0);
if (ret == 0)
usage(exe_name);

return (int) ret;
}

/* Parse a size argument, which is either an integer or two integers
separated by a colon, denoting a range. */
static void
parse_size_arg(const char *arg, const char *exe_name,
size_t *blk_min, size_t *blk_max)
{
long int ret;
char *endptr;

ret = strtol(arg, &endptr, 0);

if (ret == 0)
usage(exe_name);

*blk_min = ret;

if (endptr && *endptr == ':') {
ret = strtol(endptr + 1, NULL, 0);

if (ret == 0)
usage(exe_name);
}

*blk_max = ret;

if (*blk_min > *blk_max)
usage(exe_name);
}

/* Get a random block size between blk_min and blk_max. */
static size_t
get_random_block_size(size_t blk_min, size_t blk_max,
struct lran2_st *lran2_state)
{
size_t blk_size;

if (blk_max > blk_min) {
blk_size = blk_min + (lran2(lran2_state) % (blk_max - blk_min));
} else
blk_size = blk_min;

return blk_size;
}

static void
run_alloc_benchmark(int loops, size_t blk_min, size_t blk_max,
void **blk_array, size_t num_blks, bool clear,
struct lran2_st *lran2_state)
{
while (loops--) {
int next_idx = lran2(lran2_state) % num_blks;
size_t blk_size = get_random_block_size(blk_min, blk_max, lran2_state);

#ifdef DEBUG
printf("%06d malloc size %zu ", counter++, blk_size);
#endif
if (blk_array[next_idx]) {
#ifdef DEBUG
printf("free addr %p ", blk_array[next_idx]);
#endif
OPDealloc(blk_array[next_idx]);
}

/* Insert the newly alloced block into the array at a random point. */
blk_array[next_idx] = OPMallocRaw(heap, blk_size);
#ifdef DEBUG
printf("got addr %p\n", blk_array[next_idx]);
#endif
if (clear)
memset(blk_array[next_idx], 0, blk_size);
}

/* Free up all allocated blocks. */
for (size_t i = 0; i < num_blks; i++) {
if (blk_array[i])
OPDealloc(blk_array[i]);
}
}

struct alloc_desc {
/* Generic fields. */
int loops;
size_t blk_min;
size_t blk_max;
void **blk_array;
size_t num_blks;
bool clear;
};

static void start_bench(void *arg)
{
struct alloc_desc *desc = arg;
struct lran2_st lran2_state;

lran2_init(&lran2_state, time(NULL) ^ getpid());

run_alloc_benchmark(desc->loops, desc->blk_min, desc->blk_max,
desc->blk_array, desc->num_blks, desc->clear,
&lran2_state);
}

static void stop_bench(void *arg)
{
struct alloc_desc *desc = arg;
if (!desc) return;
free(desc->blk_array);
}

int main(int argc, char **argv)
{
size_t blk_min = 512, blk_max = 512, num_blks = 10000;
int loops = 10000000;
bool clear = false;
int opt;

while ((opt = getopt(argc, argv, "s:l:r:t:n:b:ch")) > 0) {
switch (opt) {
case 's':
parse_size_arg(optarg, argv[0], &blk_min, &blk_max);
break;
case 'l':
loops = parse_int_arg(optarg, argv[0]);
break;
case 'n':
num_blks = parse_int_arg(optarg, argv[0]);
break;
case 'c':
clear = true;
break;
case 'h':
usage(argv[0]);
break;
default:
usage(argv[0]);
break;
}
}


struct alloc_desc desc = {
.loops = loops,
.blk_min = blk_min,
.blk_max = blk_max,
.blk_array = malloc(num_blks * sizeof(unsigned char *)),
.num_blks = num_blks,
.clear = clear,
};
assert(desc.blk_array != NULL);
memset(desc.blk_array, 0, num_blks * sizeof(unsigned char *));

assert(OPHeapNew(&heap));

start_bench(&desc);
stop_bench(&desc);

OPHeapDestroy(heap);
/*
TODO: create a cross platform high resolution timer.
struct timespec start, end;
int err = clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &start);
assert(err == 0);
err = clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &end);
assert(err == 0);
double elapsed = (end.tv_sec - start.tv_sec) +
(end.tv_nsec - start.tv_nsec) * 1e-9;
struct rusage usage;
err = getrusage(RUSAGE_SELF, &usage);
assert(err == 0);
*/


/* Dump both machine and human readable versions */
/*
printf("%u:%u:%u:%u:%u:%.6f: took %.6f s for %u malloc/free\n"
"benchmark loops of %u-%u bytes. ~%.3f us per loop\n",
blk_min, blk_max, loops,
(int)clear, usage.ru_maxrss, elapsed, elapsed, loops, blk_min,
blk_max, (double)(elapsed / loops) * 1e6);
*/

return 0;
}
1 change: 1 addition & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ AC_CONFIG_FILES([
Makefile
opic/Makefile
opic/malloc/Makefile
benchmark/Makefile
])

AC_OUTPUT
2 changes: 2 additions & 0 deletions opic/malloc/allocator.c
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@ DispatchUSpanForAddr(OPHeapCtx* ctx, Magic uspan_magic, void** addr)
UnarySpan** it = &ctx->uqueue->uspan;
while (*it)
{
ctx->sspan.uspan = *it;
switch(USpanObtainAddr(ctx, addr))
{
case QOP_SUCCESS:
Expand Down Expand Up @@ -252,6 +253,7 @@ DispatchHPageForSSpan(OPHeapCtx* ctx, Magic magic, unsigned int spage_cnt,
HugePage** it = &ctx->hqueue->hpage;
while (*it)
{
ctx->hspan.hpage = *it;
switch(HPageObtainSSpan(ctx, spage_cnt, use_full_span))
{
case QOP_SUCCESS:
Expand Down
1 change: 1 addition & 0 deletions opic/malloc/init_helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ HPageInit(HugePage* hpage, Magic magic)
{
hpage->magic = magic;
hpage->pcard = 0;
hpage->next = NULL;
HPageEmptiedBMaps(hpage,
hpage->occupy_bmap,
hpage->header_bmap);
Expand Down
14 changes: 9 additions & 5 deletions opic/malloc/inline_aux.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,11 @@ DequeueUSpan(UnarySpanQueue* uspan_queue, UnarySpan* uspan)
{
UnarySpan** it = &uspan_queue->uspan;

while (*it != uspan)
while (*it != uspan && *it)
it = &(*it)->next;

*it = (*it)->next;
if (*it)
*it = (*it)->next;

atomic_store_explicit(&uspan->state, SPAN_DEQUEUED, memory_order_release);
}
Expand All @@ -99,10 +100,13 @@ EnqueueHPage(HugePageQueue* hpage_queue, HugePage* hpage)
while (*it && (*it) < hpage)
it = &(*it)->next;

if (*it > hpage)
hpage->next = *it;
if (*it != hpage)
{
if (*it > hpage)
hpage->next = *it;

*it = hpage;
*it = hpage;
}

atomic_store_explicit(&hpage->state, SPAN_ENQUEUED, memory_order_release);
}
Expand Down

0 comments on commit 7cb2f28

Please sign in to comment.